﻿using BCCommon;
using BCCommon.Enums;
using BCData.Sim.Company.Position;
using BCDto.Sim.Company.Position;
using BCEntity.Sim.Company.Position;
using BCEntity.Common.EntityNameConst;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BCEntity.Sim.Company.Department;
using BCData.Sim.Company.Department;
using BCData.Sim.Company.Company;
using BCData.Sim.Admin.StaffOrganizationMappingRecord;
using BCDto.Sim.Admin.Admin;

namespace BCService.Sim.Company.Position
{
	public class PositionService : IPositionService
	{
		private readonly IDatabaseContext databaseContext;
		private readonly IRedisService redisService;
		private readonly IPositionData positionData;
		private readonly ICompanyData companyData;
		private readonly IDepartmentData departmentData;
		private readonly IStaffOrganizationMappingRecordData staffOrganizationMappingRecordData;
		private readonly string key = string.Format("{0}", EntityNameConst.PositionEntity);

		public PositionService(IDatabaseContext databaseContext,
			IRedisService redisService,
			IPositionData positionData,
			ICompanyData companyData,
			IDepartmentData departmentData,
			IStaffOrganizationMappingRecordData staffOrganizationMappingRecordData)
		{
			this.databaseContext = databaseContext;
			this.redisService = redisService;
			this.positionData = positionData;
			this.companyData = companyData;
			this.departmentData = departmentData;
			this.staffOrganizationMappingRecordData = staffOrganizationMappingRecordData;
		}

		#region 检查岗位是否存在
		public bool Exists(int positionId)
		{
			return this.positionData.Exists(positionId).GetAwaiter().GetResult();
		}
		#endregion

		#region 添加岗位
		public PositionDto Add(PositionRequestDto requestDto,AdminDto adminDto)
		{
            if (!this.companyData.CheckCompanyExists(requestDto.CompanyId).GetAwaiter().GetResult())
            {
				throw new ArgumentException("此公司信息不存在!");
            }
			if (!this.departmentData.CheckDepartment(requestDto.DepartmentId).GetAwaiter().GetResult())
			{
				throw new ArgumentException("此部门信息不存在!");
			}
			if (requestDto.ParentPositionId.HasValue)
			{
				if (!this.Exists(requestDto.ParentPositionId.Value))
				{
					throw new ArgumentException("所属岗位信息不存在!");
				}
			}
			var entity = requestDto.As<PositionEntity>();
			entity.CreateAdminName = adminDto.FullName;
			entity.CreateAdminId = adminDto.AdminId;

			var result = this.positionData.Add(entity).GetAwaiter().GetResult().As<PositionDto>();
			this.redisService.DeleteMultipleKey(key, false);
			return result;
		}
		#endregion

		#region 修改岗位
		public PositionDto Update(PositionPutDto putDto, AdminDto adminDto)
		{
			if (!this.Exists(putDto.PositionId))
			{
				throw new ArgumentException("此记录不存在!");
			}
			if (!this.companyData.CheckCompanyExists(putDto.CompanyId).GetAwaiter().GetResult())
			{
				throw new ArgumentException("此公司信息不存在!");
			}
			if (!this.departmentData.CheckDepartment(putDto.DepartmentId).GetAwaiter().GetResult())
			{
				throw new ArgumentException("此部门信息不存在!");
			}
			if (putDto.ParentPositionId.HasValue)
			{
				if (!this.Exists(putDto.ParentPositionId.Value))
				{
					throw new ArgumentException("所属岗位信息不存在!");
				}
			}
			var entity = putDto.As<PositionEntity>();
			entity.EditAdminName = adminDto.FullName;
			entity.EditAdminId = adminDto.AdminId;
			var result = this.positionData.Update(entity).GetAwaiter().GetResult().As<PositionDto>();
			this.redisService.DeleteMultipleKey(key, false);
			return result;
		}
		#endregion

		#region 删除岗位
		public bool Delete(int positionId)
		{
			if (!this.Exists(positionId))
			{
				throw new ArgumentException("此记录不存在!");
			}
			var position = this.Get(positionId);
			if (this.staffOrganizationMappingRecordData.InUse(position.CompanyId, position.PositionNo).GetAwaiter().GetResult())
			{
				throw new ArgumentException("此岗位已被使用，无法修改!");
			}
			var result = this.positionData.Delete(positionId).GetAwaiter().GetResult();
			this.redisService.DeleteMultipleKey(key, false);
			return result;
		}
		#endregion

		#region 获取岗位
		public PositionDto Get(int positionId)
		{
			string cacheKey = this.redisService.GetKey(key, positionId);
			var result = this.redisService.TryGet(cacheKey, () =>
			{
				var data = this.positionData.GetEntity(positionId).GetAwaiter().GetResult();
				return data;
			}, TimeSpan.FromDays(1));
			return result.As<PositionDto>();
		}
		public PositionDto Get(int companyId, int departmentId,string positionNo)
		{
			string cacheKey = this.redisService.GetKey(key, companyId, departmentId, positionNo);
			var result = this.redisService.TryGet(cacheKey, () =>
			{
				var data = this.positionData.GetEntity(companyId, departmentId, positionNo).GetAwaiter().GetResult();
				return data;
			}, TimeSpan.FromDays(1));
			return result.As<PositionDto>();
		}
		#endregion

		#region 获取岗位列表
		public IEnumerable<PositionDto> GetList(int companyId,int? departmentId, bool? enabled)
		{
			string cacheKey = this.redisService.GetKey(key, companyId, departmentId, enabled);
			var result = this.redisService.TryGet(cacheKey, () =>
			{
				return this.positionData.GetList(companyId,departmentId,enabled).GetAwaiter().GetResult();
			}, TimeSpan.FromDays(1));
			return result.As<IEnumerable<PositionDto>>();
		}
        #endregion

        #region 获取岗位树形列表
		public List<object> GetPositionTree(int companyId,int? departmentId)
        {
			string cacheKey = this.redisService.GetKey("PositionTree", companyId, departmentId);
			var result = this.redisService.TryGet(cacheKey, () =>
			{
				IEnumerable<PositionEntity> positionEntities = this.positionData.GetList(companyId, departmentId, null).GetAwaiter().GetResult();
				List<object> resultTree = GetCompanyPositionTree(positionEntities);
				return resultTree;
			}, TimeSpan.FromDays(1));
			return result;
		}
		private List<object> GetCompanyPositionTree(IEnumerable<PositionEntity> positionEntities)
        {
			List<object> resultTree = new List<object>();
			foreach(var item in positionEntities.Where(p=>!p.ParentPositionId.HasValue))
            {
				var children = GetChildrenPositionTree(positionEntities, item.PositionId);
                if (children.Any())
                {
					object child = new
					{
						Title = item.PositionName,
						Key = string.Format("{0}-{1}-{2}", item.CompanyId, item.DepartmentId, item.PositionId),
						Origin = item,
						Children = children.ToArray()
					};
					resultTree.Add(child);
				}
                else
                {
					object child = new
					{
						Title = item.PositionName,
						Key = string.Format("{0}-{1}-{2}", item.CompanyId, item.DepartmentId, item.PositionId),
						Origin = item,
						isLeaf = true
					};
					resultTree.Add(child);
				}
			}
			return resultTree;
        }
		private List<object> GetChildrenPositionTree(IEnumerable<PositionEntity> positionEntities,int parentPositionId)
        {
			List<object> resultTree = new List<object>();
			var list = positionEntities.Where(p => p.ParentPositionId == parentPositionId);
            if (list.Any())
            {
				foreach (var item in list)
				{
					var children = GetChildrenPositionTree(positionEntities, item.PositionId);
                    if (children.Any())
                    {
						object child = new
						{
							Title = item.PositionName,
							Key = string.Format("{0}-{1}-{2}", item.CompanyId, item.DepartmentId, item.PositionId),
							Origin = item,
							Children = children.ToArray()
						};
						resultTree.Add(child);
					}
                    else
                    {
						object child = new
						{
							Title = item.PositionName,
							Key = string.Format("{0}-{1}-{2}", item.CompanyId, item.DepartmentId, item.PositionId),
							Origin = item,
							isLeaf = true
						};
						resultTree.Add(child);
					}
				}
			}
			return resultTree;
		}
        #endregion

        #region 获取岗位分页
        public PageableList<PositionDto> Query(int? companyId, int? departmentId, bool? enabled, DateTime? start, DateTime? end, string sortName, bool? ascending, int pageIndex, int pageSize)
		{
			string cacheKey = this.redisService.GetKey(key, companyId, departmentId, enabled, start, end, sortName, ascending, pageIndex, pageSize);
			var result = this.redisService.TryGet(cacheKey, () =>
			{
				var data = this.positionData.Query(companyId, departmentId, enabled, start, end, sortName, ascending, pageIndex, pageSize).GetAwaiter().GetResult();
				return new PageableList<PositionDto>
				{
					Count = data.Item2,
					Items = data.Item1.As<IEnumerable<PositionDto>>(),
					PageIndex = pageIndex,
					PageSize = pageSize,
					ServerTime = DateTime.Now
				};
			}, TimeSpan.FromMinutes(30));

			return result;
		}
		#endregion

		#region 启用岗位
		public bool Enabled(int positionId)
		{
			if (!this.Exists(positionId))
			{
				throw new ArgumentException("此记录不存在!");
			}
			var result = this.positionData.Enabled(positionId).GetAwaiter().GetResult();
			string cacheKey = this.redisService.GetKey(key, positionId);
			this.redisService.DeleteAsync(cacheKey);
			return result;
		}
		#endregion

		#region 禁用岗位
		public bool Disabled(int positionId)
		{
			if (!this.Exists(positionId))
			{
				throw new ArgumentException("此记录不存在!");
			}
			var result = this.positionData.Disabled(positionId).GetAwaiter().GetResult();
			string cacheKey = this.redisService.GetKey(key, positionId);
			this.redisService.DeleteAsync(cacheKey);
			return result;
		}
		#endregion
	}
}